#include "caldata.h"

string OP = "+-*/()";//存放着运算符
string DATA = "0123456789.";//存放着数字
bool isOPerator(const char ch)
{
    int i=0;
    while(OP[i]!=ch&&i<=3)i++;
    if(i>3) return false;
    else return true;
}//判断是否为运算符
bool isNumber(const char ch)
{
    int i=0;
    while(DATA[i]!=ch&&i<=10)i++;
    if(i>10) return false;
    else return true;
}//判断是否为数字

bool isStringLegal(string str)
{
//    string str = inputSting.toStdString();
    /* 判断是否是空串 */
    if (str.empty()) return false;
    /*   不为空时               */
    // 开头和结尾是否为数字
    char firstCh = str[0];
    char lastCh = str[str.size()-1];
    if((!(isNumber(firstCh)||firstCh=='('))||(!(isNumber(lastCh)||lastCh==')'))) return false;
    /* 1.是否有未知符号；2.是否有连续的符号；3.括号是否出现背靠背   */
    int flagParentheses=0;//小括号标识
    for(size_t i=0;i<str.size();i++)
    {
        /* 是否有除了加减乘除括号之外的字符 */
        char chNow = str[i];//当前处理的字符
        /*  未知符号判断 */
        if((!isNumber(chNow))&&(!(isOPerator(chNow)||chNow==OP[4]||chNow==OP[5]))) return false;
        /* 连续符号判断    */
        if(i>1&&isOPerator(chNow)&&isOPerator(str[i-1])) return false;
        /* 括号是否成对出现 */
        if(chNow==OP[4]) flagParentheses++;
        if(chNow==OP[5]) flagParentheses--;
        if(flagParentheses<0) return false;//先出现了‘）’
    }
    //4.括号是否成对出现
    if(flagParentheses!=0) return false;
    return true;
}//表达式合法性判断

//中缀表达式转后缀（逆波兰表达式）
string infix2Suffix(string s_mid)
{
    string s_beh = "";
    stack<char> stk;
    //    stack<char> stk1;

    map<char, int> op;//利用map来实现运算符对应其优先级
    op['('] = 0;
    op[')'] = 0;
    op['+'] = 1;
    op['-'] = 1;
    op['*'] = 2;
    op['/'] = 2;
    string::iterator it = s_mid.begin();;
    while (it != s_mid.end())
    {
        if (op.count(*it))//判断该元素是否为运算符
        {
            if (*it == ')')//情况2
            {
                while (stk.top() != '(')
                {
                    s_beh += stk.top();
                    stk.pop();
                }
                stk.pop();
            }
            else if (stk.empty() || *it == '(' || op[*it] > op[stk.top()])//情况1、情况3
            {
                stk.push(*it);
            }
            else if (op[*it] <= op[stk.top()])//情况3
            {
                while (op[*it] <= op[stk.top()] && (!stk.empty()))
                {
                    s_beh += stk.top();
                    stk.pop();
                    if (stk.empty()) break;
                }
                stk.push(*it);
            }
        }
        else
        {
            if (it > s_mid.begin() && op.count(*(it - 1))) s_beh += '#';
            s_beh += *it;
        }
        it++;
        if (it == s_mid.end())//当中缀表达式输出完成，所有元素出栈
        {
            while (!stk.empty())
            {
                s_beh += stk.top();
                stk.pop();
            }
            break;
        }
    }
    return s_beh;
}//中缀表达式转后缀（逆波兰表达式）

/* 将后缀表达式存入向量中 */
vector<string> suffixPutInVector(string s_beh)
{
    string stringNow;
    vector<string> reSult;
    string::const_iterator iter = s_beh.cbegin();
    while (iter!=s_beh.cend())
    {
        if (isOPerator(*iter))
        {
            if (!stringNow.empty())
            {
                reSult.push_back(stringNow);
            }
            stringNow = *iter;
            reSult.push_back(stringNow);
            stringNow = "";
            iter++;
        }
        else if (*iter == '#')
        {
            if (!stringNow.empty())
            {
                reSult.push_back(stringNow);
                stringNow = "";
            }
            iter++;

        }
        else stringNow += *iter++;
    }
    return reSult;
}//将后缀表达式存入向量中

/* 根据逆波兰表达式求表达式的值 */
double getTheResult(vector<string>& vec)
{
    vector<string>::iterator it;
    stack<double> sta;
    string strTemp;
    double d = 0, d1 = 0, d2 = 0;
    for (it = vec.begin(); it != vec.end(); it++)
    {
        strTemp = (*it);

        if (strTemp == "+")
        {
            d1 = sta.top();
            sta.pop();

            d2 = sta.top();
            sta.pop();

            d = d1 + d2;
            sta.push(d);
        }
        else if (strTemp == "-")
        {
            d1 = sta.top();
            sta.pop();

            d2 = sta.top();
            sta.pop();

            d = d2 - d1;
            sta.push(d);
        }
        else if (strTemp == "*")
        {
            d1 = sta.top();
            sta.pop();

            d2 = sta.top();
            sta.pop();

            d = d2 * d1;
            sta.push(d);
        }
        else if (strTemp == "/")
        {
            d1 = sta.top();
            sta.pop();

            d2 = sta.top();
            sta.pop();

            d = d2 / d1;
            sta.push(d);
        }
        else
        {
            const char* p = strTemp.c_str();
            d = atof(p);
            sta.push(d);
        }
    }
    return sta.top();
}//根据逆波兰表达式求表达式的值


Caldata::Caldata(string inputString)
{
    if(isStringLegal(inputString)) rpNotation = infix2Suffix(inputString);
    else rpNotation = "Illegal input";
}//构造函数
bool Caldata::islegalinput()
{
    if(rpNotation == "Illegal input") return false;
    else return true;
}//非法判断
string Caldata::getResult()
{
    if(rpNotation == "Illegal input") return rpNotation;
    else
    {
        vector<string> vec =suffixPutInVector(rpNotation);
        double reSult = getTheResult(vec);
        /*double转string */
        stringstream ss;
          ss << reSult;                                          //吃进去各种类型，存成char
          string s;
          ss >> s;
        return s;
    }
}//得出结果
